package mainPackage;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;


import register.Register;
import register.RegisterID;
import bplustree.BPlusTree;
import bplustree.BadChecksumException;
import FilesManagers.CantOpenFileException;
import FilesManagers.FileManager;
import FilesManagers.FullUrlManager;
import FilesManagers.NoMoreLinesException;
import FilesManagers.RemoteUrlManager;

import Filters.FullFilter;


/*
 *FIXME - Agregar excepciones a todo.
 * */

public class IndexManager {
	
	private String urls;
	private FileManager manejadorUrls;
	private FullFilter filtroLinea;
	private int contadorUrls;
	private String urlsIndexedsFile,urlsTemp;
	private ArrayList<String> listaPalabras;
	private boolean logger;
	//private BPlusTree arbol;
	public IndexManager(String urls, FullFilter filtro) throws CantOpenFileException{
		this.urls=urls;
		filtroLinea= filtro;
		manejadorUrls = new FileManager();
		//manejadorUrls.cargarArchivo(this.urls);
		//manejadorUrls.setMarcadorComentario('#');
		contadorUrls=0;
		urlsIndexedsFile ="urlIndexadas.txt";
		urlsTemp="urlsTemp.txt";
		logger=false;
	}
	
	public IndexManager(String urls, String urlsIndexadas,FullFilter filtro) throws CantOpenFileException{
		this(urls,filtro);
		urlsIndexedsFile =urlsIndexadas;
		
	}
		
	private int getUrlNumber(String url){
		FileManager manejadorArchivo = new FileManager();
		try {
			manejadorArchivo.cargarArchivo(urlsIndexedsFile);
			
			
		} catch (CantOpenFileException e1) {
			// TODO Bloque catch generado automáticamente
			contadorUrls++;
			FileManager.append(urlsIndexedsFile,""+contadorUrls+","+url+"\n");
			return contadorUrls;
			//e1.printStackTrace();
		}
		
		
		String linea=null;
		try {
			while((linea=manejadorArchivo.obtenerSiguienteLinea())!=null){
				String[] args=linea.split(",");
				if(args[1].equals(url)){
					return Integer.parseInt(args[0]);
					
				}
				if(args[0]!=null && args[0]!="")this.contadorUrls=Integer.parseInt(args[0]);
				
			}
		} catch (NoMoreLinesException e) {
			contadorUrls++;
			//System.out.println("No estaba, lo agrego em eñl catch "+contadorUrls+","+url+"\n");
			FileManager.append(urlsIndexedsFile,""+contadorUrls+","+url+"\n");
			return contadorUrls;
			// TODO Bloque catch generado automáticamente
			//e.printStackTrace();
		}
		
		contadorUrls++;
		//System.out.println("No estaba, lo agrego "+contadorUrls+","+url+"\n");
		FileManager.append(urlsIndexedsFile,contadorUrls+","+url+"\n");
		return contadorUrls;
		
		
		
	}
	private String getUrlNumber(int nro) throws CantOpenFileException{
		FileManager manejadorArchivo = new FileManager();
		try {
			manejadorArchivo.cargarArchivo(this.urlsIndexedsFile);
		} catch (CantOpenFileException e1) {
			// TODO Bloque catch generado automáticamente
			//e1.printStackTrace();
			throw new CantOpenFileException("No existe el archivo con las url indexadas, debe generar el arbol nuevamente");
		}
		String linea=null;
		try {
			while((linea=manejadorArchivo.obtenerSiguienteLinea())!=null){
				String[] args=linea.split(",");
				if(Integer.parseInt(args[0])==(nro)){
					return args[1];
					
				}
				
				
			}
		} catch (NoMoreLinesException e) {
			//e.printStackTrace();
			
		}finally{
			manejadorArchivo.cerrarArchivo();			
			
		}
		return null;
	}
	
	
	private void devolverAuxiliar(String linea){
		linea = filtroLinea.procesarLinea(linea);
	
		if((linea.trim().compareTo("")!=0)||(filtroLinea.getUltimaLinea())){ 
			//System.out.println(linea);
			String palabras[]= linea.split(" ");
			for(int i=0;i<palabras.length;i++){
				int posLista =listaPalabras.indexOf(palabras[i]);
				
				/*Si ya existe no la pongo en llista otra vez, deberia aumentar el contador*/
				
				if(posLista==-1){
					listaPalabras.add(palabras[i]);
				//System.out.println(palabras[i]);
				}else{
					//deberia aculmular las cantidades, todavia no es necesario ------------- FINISH ME
					//System.out.println("----Ya existia "+palabras[i]);
				}
				
			}
		}
		
	}
	
	
	/* Lee el siguiente url, lo copia a disco en un archivo temporal,  extrae el numero y la lista de palabras 
	 * y los retorna en la un objeto de tipo DatosUrl
	 *  */
	public DatosUrl devolverPalabrasSiguiente () throws CantOpenFileException{
		DatosUrl datosUrl = new DatosUrl();
		//ArrayList<String> listaPalabras = new ArrayList<String>();
		listaPalabras = new ArrayList<String>();
		int contadorUrls=0;
		String archivoTemporal="temp.html";
		String linea="";
		
		FileManager manejadorArchivo = new FileManager();
		
		//try{
		FullUrlManager url = new FullUrlManager();

		try{
			
			if(((linea = manejadorUrls.obtenerSiguienteLinea())!=null)){
				//if(itHtmls.hasNext())FileManager.append("urls.txt","\n");
				
					if(logger)FileManager.append("log.txt","**************************\n");
					System.out.println("**************************");
					if(logger)FileManager.append("log.txt","Procesando URL "+linea+"\n");
					System.out.println("Procesando URL "+linea);
					//System.out.println("**************************");
					/*El primer parametro es la url remota, el segundo el nombre que le quiero poner en disco, si se deja vacio usa el mismo nombre del html remoto*/
					try{
						url.copiar(linea,archivoTemporal);
					}catch(CantOpenFileException e){
						System.err.println(e.getMessage());
						return devolverPalabrasSiguiente();
					}
					
					contadorUrls=this.getUrlNumber(linea);
					
					//System.out.println("Quiero abrir la url con codificacion "+url.getCodificacion());
					manejadorArchivo.cargarArchivo(archivoTemporal,url.getCodificacion());
					try{
						filtroLinea.setUltimaLinea(false);
						while((linea = manejadorArchivo.obtenerSiguienteLinea())!=null){
							devolverAuxiliar(linea);
						}
						filtroLinea.setUltimaLinea(true);
						devolverAuxiliar(" ");
					}catch(NoMoreLinesException e){
						//System.out.println(e.getMessage());
						filtroLinea.setUltimaLinea(true);
						devolverAuxiliar(" ");
						manejadorArchivo.cerrarArchivo();
						
	
					}
				//}
			}else{
				return null;
				
			}
		}catch(NoMoreLinesException e){
			System.out.println(e.getMessage());
			manejadorUrls.cerrarArchivo();
			datosUrl= null;

		}
		/*}catch(CantOpenFileException e){
			System.out.println(e.getMessage());

		}*/
		//manejadorArchivo.cerrarArchivo();
		
		FileManager.borrar(archivoTemporal);
		
		if(datosUrl!=null){
			datosUrl.setItPalabras(listaPalabras.iterator());
			datosUrl.setNumeroUrl(contadorUrls);
		}
		return datosUrl;



	}

	/*Lo uso para continuar con algun indice generado anteriormente*/
	public void makeIndex(String archArbol, Integer nodeSize ) throws CantOpenFileException{
		DatosUrl datosUrl;

		this.organizarUrls();
		try {
			BPlusTree arbol = new BPlusTree(archArbol,nodeSize);
			Register registro = new Register();
			RegisterID IdRegistro = new RegisterID();
			
			//this.arbol = new BPlusTree(archArbol);
			while((datosUrl = this.devolverPalabrasSiguiente())!=null){
				Iterator itPalabras = datosUrl.getItPalabras();
				int numeroUrl =	datosUrl.getNumeroUrl();
			
				//System.out.println("Indexando la Url ...por favor espere.");
				String palabra="";
				while(itPalabras.hasNext()){
					palabra=itPalabras.next().toString().trim();
					if(!palabra.equals(""))
					{	
						//if(logger)FileManager.append("log.txt",palabra+" ");
						IdRegistro.setID(palabra);
						registro.setID(IdRegistro);
						registro.setAtribute(numeroUrl);
						arbol.insert(/*new Register(new RegisterID(palabra),numeroUrl)*/registro);
					}
				}
				//if(logger)FileManager.append("log.txt","\n\n");
				//System.out.println("Finalizada insercion, comenzando listado");
				//arbol.list();
				//arbol.finalize();
			
			}
			manejadorUrls.cerrarArchivo();
			FileManager.borrar(urlsTemp);
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadChecksumException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			
		
		
	}
	/*Lo uso para probar desde cero el indice, o sea, borrando tolo lo anterio*/
	public void makeNewIndex(String archArbol, Integer nodeSize) throws CantOpenFileException{
		/*Borro los archivos de trabajo y vuevlo a abrir el de urls
		 * para dar la posibilidad a cambiar el contenido del mismo
		 * sin cerrar el programa y volverlo a abrir*/
		
		FileManager.borrar(archArbol);
		this.contadorUrls=0;
		FileManager.borrar(urlsIndexedsFile);
		
		//manejadorUrls.cerrarArchivo();		
		this.makeIndex(archArbol,nodeSize);
		
	}
	
	private void organizarUrls() throws CantOpenFileException{
		/*Proceso el archivo de urls para armarme un archivo temporal, en este
		 * se incluiran las url del tipo http , los archivos locales y los resultados 
		 * de los directorios ya procesados, o sea la direccion de sus archivos */
		FileManager.borrar(urlsTemp);
		manejadorUrls = new FileManager();
		manejadorUrls.cargarArchivo(this.urls);
		manejadorUrls.setMarcadorComentario('#');
		String linea;
		FullUrlManager url = new FullUrlManager();
		try {
			while(((linea = manejadorUrls.obtenerSiguienteLinea())!=null)){
				Iterator<String> itHtmls = url.getItOfHtmlFiles(linea);
				/*Uso un archivo temporal por si tengo directorios en los cuales debo procesar sus archivos*/
				while(itHtmls.hasNext()){
					FileManager.append(urlsTemp,itHtmls.next()+"\n");//linea = itHtmls.next();
				}
			}
		} catch (NoMoreLinesException e) {
			// TODO Bloque catch generado automáticamente
			//e.printStackTrace();
		}
		manejadorUrls.cerrarArchivo();
		manejadorUrls.cargarArchivo(urlsTemp);
		
		
	}
	
	private String[] obtenerUrlRegistro(Register reg) throws CantOpenFileException{
		
		
		String args[]=reg.toStringList().split("\\|\\|");
		args=args[1].trim().split("\\|");
		for (int i=0;i<args.length;i++){
			args[i]=this.getUrlNumber(Integer.parseInt(args[i]));
			
		}
		return args;		
	}
	
	
	
	public String[] searchIndex(String archArbol,String objetivo) throws CantOpenFileException{
		BPlusTree arbol;
		
		try {
			//if(this.arbol==null)this.arbol = new BPlusTree(); // para que con sucesivas consultas no se habra el archiv constantemente
			arbol = new BPlusTree(archArbol,128); //el 128 es dummy, el archivo contiene el nodeSize
			Register tempReg=arbol.search(new RegisterID(objetivo));
			System.out.println("Registro más proximo encontrado:");
			System.out.println("Size; ID||At1|At2|At...");
			System.out.println(tempReg.toStringList());
			return this.obtenerUrlRegistro(tempReg);
			//arbol.finalize();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
			throw new CantOpenFileException("No se pudo abrir el archivo del indice");
		}catch (BadChecksumException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
			throw new CantOpenFileException("No se pudo abrir el archivo del indice, esta corrupto");
		}
		
		
	}
	
	public void listIndex(String archArbol) throws CantOpenFileException{
		BPlusTree arbol;
		
		try {
			arbol = new BPlusTree(archArbol,128);//el 128 es dummy, el archivo contiene el nodeSize
			arbol.list();
			
		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}

	public boolean isLogger() {
		return logger;
	}

	public void setLogger(boolean logger) {
		this.logger = logger;
	}
	



}